//
//  BluetoothController.m
//  Light
//
//  Created by 嘉恒 汪 on 15/12/28.
//  Copyright © 2015年 骁唐. All rights reserved.
//

#import "BluetoothController.h"


@interface BluetoothController()

@end


@implementation BluetoothController {
    BOOL inited;
    CBCentralManager *myCenter;
    //state
    NSInteger scanState;
    NSInteger connectState;
    NSInteger serviceState;
    NSInteger characteristicState;
    NSInteger readState;
    eventBlock connectBlock;
    //    CBPeripheral *m_Peripheral;
}

+ (CBUUID *) uartServiceUUID
{
    return [CBUUID UUIDWithString:@"FFF0"];
}

+ (CBUUID *) txCharacteristicUUID
{
    return [CBUUID UUIDWithString:@"FFF2"];
}

+ (CBUUID *) rxCharacteristicUUID
{
    return [CBUUID UUIDWithString:@"FFF1"];
}

+ (CBUUID *) deviceInformationServiceUUID
{
    return [CBUUID UUIDWithString:@"180A"];
}

+ (CBUUID *) hardwareRevisionStringUUID
{
    return [CBUUID UUIDWithString:@"2A27"];
}


static BluetoothController* _defaultBTServer = nil;
-(NSInteger)getScanState
{
    return scanState;
}
-(NSInteger)getConnectState
{
    return connectState;
}
-(NSInteger)getServiceState
{
    return serviceState;
}
-(NSInteger)getCharacteristicState
{
    return characteristicState;
}
-(NSInteger)getReadState
{
    return readState;
}


+(BluetoothController*)defaultBTServer
{
    if (nil == _defaultBTServer) {
        _defaultBTServer = [[BluetoothController alloc]init];
        
        [_defaultBTServer initBLE];
    }
    
    AppDelegate * delegate = [[UIApplication sharedApplication]delegate];
    
    delegate.mgr = _defaultBTServer;
    
    return _defaultBTServer;
}

-(void)initBLE
{
    if (inited) {
        return;
    }
    inited = TRUE;
    self.delegate = nil;
    self.discoveredPeripherals = [NSMutableArray array];
    //    self.services = [NSMutableArray array];
    self.selectPeripheral = nil;
    connectState = KNOT;
    connectBlock = nil;
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], CBCentralManagerOptionShowPowerAlertKey, @"zStrapRestoreIdentifier",CBCentralManagerOptionRestoreIdentifierKey,nil];
    myCenter = [[CBCentralManager alloc]
                initWithDelegate:self
                queue:nil//dispatch_queue_create("com.myBLEQueue", NULL)
                options:options]; // TODO: options
    NSLog(@"init bt server ........");
}

-(void)finishBLE
{
    //??
}

#pragma mark -
#pragma mark 开始扫描（供其他Controller中调用）
-(void)startScan
{
    [self startScan:3];
}

#pragma mark -
#pragma mark 重新开始扫描 参数没有什么用。
-(void)startScan:(NSInteger)forLastTime
{
    while (self.selectPeripheral.state == CBPeripheralStateConnected)
    {//新添加的。
        NSLog(@"等待设备断开:%@",self.selectPeripheral.name);
        [myCenter cancelPeripheralConnection:self.selectPeripheral];
    }
    if (scanState == KING)//正在连接
    {
        [self stopScan:NO];//停止扫描，NO
    }
    [self.discoveredPeripherals removeAllObjects];//清空数组中扫描到的设备
    scanState = KING;//正在连接
    //0:retrive
//#if 1
//    //method 1:
//    NSArray *atmp = [NSArray arrayWithObjects:[CBUUID UUIDWithString:UUIDPrimaryService],[CBUUID UUIDWithString:UUIDPrimaryService2], nil];
//    NSArray *retrivedArray = [myCenter retrieveConnectedPeripheralsWithServices:atmp];
//    NSLog(@"retrivedArray:\n%@",retrivedArray);
//    
//    for (CBPeripheral* peripheral in retrivedArray) {
//        [self addPeripheral:peripheral advertisementData:nil  RSSI:nil];
//    }
//    
//    //method 2:
//    //    [myCenter retrieveConnectedPeripherals];//XXX: deprecated\ˈdɛprɪˌket\ but still work
//    
//#endif
    //1: scan
    //    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], CBCentralManagerScanOptionAllowDuplicatesKey, nil];
    //    [myCenter scanForPeripheralsWithServices:[NSArray arrayWithObject:[CBUUID UUIDWithString:@"0xFFA0"]]  options:options];
    [myCenter scanForPeripheralsWithServices:nil options:nil];//开始盲扫
    if (forLastTime > 0)
    {
        [NSObject cancelPreviousPerformRequestsWithTarget:self
                                                 selector:@selector(stopScan)
                                                   object:nil];//取消延迟执行 stopScan
        [self performSelector:@selector(stopScan)
                   withObject:nil
                   afterDelay:forLastTime];//延时forLastTime时间后停止扫描。（延迟执行）
    }
}

#pragma mark -
#pragma mark 停止扫描（根据传值判断）
-(void)stopScan:(BOOL)withOutEvent
{
    if (scanState != KING) {//如果状态不等于“正在连接”
        return;
    }
    NSLog(@"stop scan ...");
    scanState = KSUCCESS;//连接成功
    
    [myCenter stopScan];//断开连接
    if(withOutEvent)
        return;//直接return
    if (self.delegate) {//如果
        if([(id)self.delegate respondsToSelector:@selector(didStopScan)]){//调用协议方法
            [self.delegate didStopScan];//断开连接
        }
    }
}

#pragma mark -
#pragma mark 停止扫描
-(void)stopScan
{
    [self stopScan:FALSE];//传值false
}

#pragma mark -
#pragma mark 断开连接
-(void)cancelConnect
{
    if (myCenter && self.selectPeripheral)
    {
        if(self.selectPeripheral.state == CBPeripheralStateConnecting)
        {//正在连接
            NSLog(@"timeout cancel connect to peripheral:%@",self.selectPeripheral.name);
            [myCenter cancelPeripheralConnection:self.selectPeripheral];//断开连接
            connectState = KNOT;//未连接标志
        }
    }
}

#pragma mark -
#pragma mark 连接设备
-(void)connect:(PeriperalInfo *)peripheralInfo
{
    
    while (self.selectPeripheral.state == CBPeripheralStateConnected){
        NSLog(@"等待设备断开:%@",self.selectPeripheral.name);
        
        [myCenter cancelPeripheralConnection:self.selectPeripheral];
    }
    if ([TJJDefines isNull:myCenter] || [TJJDefines isNull:peripheralInfo])
    {
        return;
    }
    NSLog(@"connecting to peripheral:%@,RSSI:%@",peripheralInfo.peripheral.name,peripheralInfo.RSSI);
    [myCenter connectPeripheral:peripheralInfo.peripheral options:@{CBConnectPeripheralOptionNotifyOnConnectionKey: @YES, CBConnectPeripheralOptionNotifyOnDisconnectionKey: @YES, CBConnectPeripheralOptionNotifyOnNotificationKey: @YES}];
    
    self.selectPeripheral = peripheralInfo.peripheral;
    connectState = KING;
    AppDelegate * delegate = [[UIApplication sharedApplication] delegate];
    if ([delegate.fromwhere isEqualToString:@"Connect"]) {
         [NSTimer scheduledTimerWithTimeInterval:4 target:self selector:@selector(cancelConnect) userInfo:nil repeats:NO];//延迟4S 中断连接
    }
}

#pragma mark -
#pragma mark 断开连接（外部调用）
-(void)disConnect
{
    if(myCenter && self.selectPeripheral)
    {
        [myCenter cancelPeripheralConnection:self.selectPeripheral];
    }
}

#pragma mark -
#pragma mark 发现服务
-(void)discoverService:(CBService*)service
{
    if(self.selectPeripheral)
    {
        characteristicState = KING;
        self.discoveredSevice = service;
        [self.selectPeripheral discoverCharacteristics:nil forService:service];
    }
    
}

#pragma mark -
#pragma mark 读取到特征值
-(void)readValue:(CBCharacteristic*)characteristic
{
    if (readState == KING) {
        NSLog(@"BTServer: should wait read over");
        return;
    }
    if (characteristic != nil) {
        self.selectCharacteristic = characteristic;
    }
    readState = KING;
    [self.selectPeripheral readValueForCharacteristic:self.selectCharacteristic];
}

#pragma mark CBCentralManagerDelegate
-(void)addPeripheralInfo:(PeriperalInfo *)peripheralInfo
{
    for(int i=0;i<self.discoveredPeripherals.count;i++)
    {//判断是否已经添加到数组中，如果已经添加了，则舍弃掉。
        PeriperalInfo *pi = self.discoveredPeripherals[i];
        if([peripheralInfo.uuid isEqualToString:pi.uuid]){
//            [self.discoveredPeripherals replaceObjectAtIndex:i withObject:peripheralInfo];
            return;
        }
    }
    int i = 0;
    for (i=0;i<self.discoveredPeripherals.count;i++)
    {//根据RSSI，也就是信号强度来进行排序。
        PeriperalInfo *pi = self.discoveredPeripherals[i];
        if ([peripheralInfo.RSSI intValue]>=[pi.RSSI intValue]) break;
        
    }
    
    [self.discoveredPeripherals insertObject:peripheralInfo atIndex:i];
    NSLog(@"Added peripheral: %@; RSSI: %@", peripheralInfo.name, peripheralInfo.RSSI);
    //[self.discoveredPeripherals addObject:peripheralInfo];
    if (self.delegate) {
        if([(id)self.delegate respondsToSelector:@selector(didFoundPeripheral)]){
            [self.delegate didFoundPeripheral];
        }
    }
}
-(void)addPeripheral:(CBPeripheral*)peripheral advertisementData:(NSDictionary*)advertisementData RSSI:(NSNumber*)RSSI
{
    PeriperalInfo *pi = [[PeriperalInfo alloc]init];
    
    pi.peripheral = peripheral;
    pi.uuid = [peripheral.identifier UUIDString];
    pi.name = peripheral.name;
    if (![pi.name isEqualToString:@"MD"])
        return;
    switch (peripheral.state) {
        case CBPeripheralStateDisconnected:
            pi.state = @"disConnected";
            break;
        case CBPeripheralStateConnecting:
            pi.state = @"connecting";
            break;
        case CBPeripheralStateConnected:
            pi.state = @"connected";
            break;
        default:
            break;
    }
    //    pi.channel = advertisementData objectForKey:
    if (advertisementData) {
        pi.localName = [advertisementData objectForKey:CBAdvertisementDataLocalNameKey];
        NSArray *array = [advertisementData objectForKey:CBAdvertisementDataServiceUUIDsKey];
        pi.serviceUUIDS = [array componentsJoinedByString:@"; "];
    }
    
    
    if (RSSI) {
        if ([RSSI integerValue] == 127 )
            pi.RSSI = @(-120);
        else
            pi.RSSI = RSSI;
    }
    
    [self addPeripheralInfo:pi];
    
}

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
    //    NSLog(@"discover peripheral: %@; advertisementData: %@; RSSI: %@", peripheral, advertisementData, RSSI);
    //NSLog(@"discover peripheral: %@; RSSI: %@", peripheral.name, RSSI);
    [self addPeripheral:peripheral advertisementData:advertisementData RSSI:RSSI];
}
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
    NSLog(@"didconnect to peripheral: %@",peripheral.name);
    
    connectState = KSUCCESS;
    if (connectBlock) {
        connectBlock(peripheral,true,nil);
        connectBlock = nil;
    }
    
    
    self.selectPeripheral = peripheral;
    self.selectPeripheral.delegate = self;
    serviceState = KING;
    [self.selectPeripheral discoverServices:@[self.class.uartServiceUUID, self.class.deviceInformationServiceUUID]];
}

#pragma mark -
#pragma mark 中断连接
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
    NSLog(@"didDisConnected peripheral: %@",peripheral.name);
    connectState = KFAILED;
    if (connectBlock) {
        connectBlock(peripheral,false,nil);
        connectBlock = nil;
    }
    if (self.delegate) {
        if([(id)self.delegate respondsToSelector:@selector(didDisconnectFromPeriph)]){
            [self.delegate didDisconnectFromPeriph];
        }
    }
}

- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
    if (self.delegate) {
        if([(id)self.delegate respondsToSelector:@selector(didDisconnectFromPeriph)]){
            [self.delegate didDisconnectFromPeriph];
        }
    }
    NSLog(@"DidFailToConnectPeripheral .....");
}



- (void)centralManager:(CBCentralManager *)central didRetrieveConnectedPeripherals:(NSArray *)peripherals
{
    NSLog(@"retrive connected peripheral %@",peripherals);
}

- (void)centralManager:(CBCentralManager *)central didRetrievePeripherals:(NSArray *)peripherals
{
    NSLog(@"retrive %@",peripherals);
    
}

- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
    NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithCapacity:0];
    AppDelegate *delegate = [[UIApplication sharedApplication]delegate];
    switch (central.state) {
        case CBCentralManagerStateUnknown:
            TJJLog(@">>>CBCentralManagerStateUnknown");
            break;
        case CBCentralManagerStateResetting:
        {//蓝牙失去连接时猛搜蓝牙
            //[self startScan:3];
            //[self.mgr scanForPeripheralsWithServices:nil options:nil];//扫描外设
            TJJLog(@">>>CBCentralManagerStateResetting");
        }
            break;
        case CBCentralManagerStateUnsupported:
        {
            TJJLog(@">>>CBCentralManagerStateUnsupported");
            TJJALERT_VIEW(@"您的手机蓝牙状态不支持，看是否禁用！");
        }
            break;
        case CBCentralManagerStateUnauthorized:
            TJJLog(@">>>CBCentralManagerStateUnauthorized");
            break;
        case CBCentralManagerStatePoweredOff:
        {//中心设备关闭
            [dict setObject:@"NO" forKey:@"disConnect"];
            delegate.Bluetooth = NO;
            [[NSNotificationCenter defaultCenter] postNotificationName:@"power" object:nil userInfo:dict];
            //    // userhead有问题
            [[NSNotificationCenter defaultCenter] postNotificationName:@"userHead" object:nil userInfo:dict];
            TJJLog(@">>>CBCentralManagerStatePoweredOff");
            TJJALERT_VIEW(@"您的手机已经禁用蓝牙！");
        }
            break;
        case CBCentralManagerStatePoweredOn:
        {//状态就绪   //扫描
            //[self startScan:3];
            //[self.mgr scanForPeripheralsWithServices:nil options:nil];
            AppDelegate *delegate = [[UIApplication sharedApplication]delegate];
            if ([delegate.fromwhere isEqualToString:@"Home"])
            {
                UserConfig *config = [UserConfig sharingUserConfig];
                NSString *hasbind = [config getConnectCool];
                if ([hasbind isEqualToString:@"1"])
                    [self startScan:3];//
            }
            if ([delegate.fromwhere isEqualToString:@"Connect"])
            {
                [self startScan:3];
            }
            TJJLog(@">>>CBCentralManagerStatePoweredOn");
        }
            break;
        default:
            break;
    }

}
    
//- (void)centralManagerDidUpdateState:(CBCentralManager *)central
//{
//    // Determine the state of the peripheral
//    if ([central state] == CBCentralManagerStatePoweredOff) {
//        NSLog(@"CoreBluetooth BLE hardware is powered off");
//    }
//    else if ([central state] == CBCentralManagerStatePoweredOn) {
//        NSLog(@"CoreBluetooth BLE hardware is powered on and ready");
//    }
//    else if ([central state] == CBCentralManagerStateUnauthorized) {
//        NSLog(@"CoreBluetooth BLE state is unauthorized");
//    }
//    else if ([central state] == CBCentralManagerStateUnknown) {
//        NSLog(@"CoreBluetooth BLE state is unknown");
//    }
//    else if ([central state] == CBCentralManagerStateUnsupported) {
//        NSLog(@"CoreBluetooth BLE hardware is unsupported on this platform");
//    }
//    
//}

- (void)centralManager:(CBCentralManager *)central willRestoreState:(NSDictionary *)dict
{
    NSLog(@"will restore ....");
}


#pragma mark CBPeripheralDelegate

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
    if (nil == error) {
        serviceState = KSUCCESS;
        //        NSLog(@"found services:\n%@",peripheral.services);
        for (CBService *s in [peripheral services])
        {
            if ([s.UUID isEqual:self.class.uartServiceUUID])
            {
                NSLog(@"Found correct service");
                self.uartService = s;
                
                [self.selectPeripheral discoverCharacteristics:@[self.class.txCharacteristicUUID, self.class.rxCharacteristicUUID] forService:self.uartService];
            }
            else if ([s.UUID isEqual:self.class.deviceInformationServiceUUID])
            {
                [self.selectPeripheral discoverCharacteristics:@[self.class.hardwareRevisionStringUUID] forService:s];
            }
        }
    }else{
        serviceState = KFAILED;
        NSLog(@"discover service failed:%@",error);
    }
}

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverIncludedServicesForService:(CBService *)service error:(NSError *)error
{
}

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
    if (nil == error) {
        characteristicState = KSUCCESS;
        self.discoveredSevice = service;
        for (CBCharacteristic *c in [service characteristics])
        {
            if ([c.UUID isEqual:self.class.rxCharacteristicUUID])
            {
                NSLog(@"Found RX characteristic");
                self.rxCharacteristic = c;
                [self.selectPeripheral setNotifyValue:YES forCharacteristic:self.rxCharacteristic];
            }
            else if ([c.UUID isEqual:self.class.txCharacteristicUUID])
            {
                NSLog(@"Found TX characteristic");
                self.txCharacteristic = c;
            }
        }
    }else{
        characteristicState = KFAILED;
        self.discoveredSevice = nil;
        NSLog(@"discover characteristic failed:%@",error);
    }
    
}

- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
    if (error)
    {
        TJJLog(@"Error discovering service: %@", [error localizedDescription]);
    }
    TJJLog(@"设置监听状态成功");
    if (self.rxCharacteristic.isNotifying)
    {
        [self.delegate didDiscoverCharacteristic];
        
    }
}

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverDescriptorsForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
    
}

- (void) peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
    if (error)
    {
        readState = KFAILED;
        NSLog(@"Error updating value for characteristic %@ error: %@", characteristic.UUID, [error localizedDescription]);
        return;
    }
    
    NSLog(@"Received data on a characteristic.%@",[characteristic value]);
    readState = KSUCCESS;
    
    if (characteristic == self.rxCharacteristic)
    {
        if (self.delegate && [(id)self.delegate respondsToSelector:@selector(didReadvalue)])
            [self.delegate didReadvalue];
    }
}

-(void)reconnect:(CBPeripheral*)peripheral
{
    //    NSLog(@"connecting to peripheral:%@,RSSI:%@",peripheralInfo.peripheral.name,peripheralInfo.RSSI);
    
    while (peripheral.state == CBPeripheralStateConnected){
        NSLog(@"等待设备断开");
        
        [myCenter cancelPeripheralConnection:peripheral];
    }
    
    [myCenter connectPeripheral:peripheral options:@{CBConnectPeripheralOptionNotifyOnConnectionKey: @YES, CBConnectPeripheralOptionNotifyOnDisconnectionKey: @YES, CBConnectPeripheralOptionNotifyOnNotificationKey: @YES}];
    
    self.selectPeripheral = peripheral;
    connectState = KING;
    
    //    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(AUTO_CANCEL_CONNECT_TIMEOUT * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    //        [self cancelConnect];
    //
    //    });
//    [NSTimer scheduledTimerWithTimeInterval:4 target:self selector:@selector(cancelConnect) userInfo:nil repeats:NO];
    //    [NSObject cancelPreviousPerformRequestsWithTarget:self
    //                                             selector:@selector(cancelConnect)
    //                                               object:nil];
    //    [self performSelector:@selector(stopScan)
    //               withObject:nil
    //               afterDelay:AUTO_CANCEL_CONNECT_TIMEOUT];
}

- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForDescriptor:(CBDescriptor *)descriptor error:(NSError *)error
{
}

- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
//    TJJLog(@"写入成功%@",characteristic.value);//characteristic 空
    // 标志位，指令发送成功
    AppDelegate * delegate = [[UIApplication sharedApplication] delegate];
    delegate.isWirteOK = YES;
}

- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForDescriptor:(CBDescriptor *)descriptor error:(NSError *)error
{
}

- (void)peripheralDidUpdateRSSI:(CBPeripheral *)peripheral error:(NSError *)error
{
}

- (void)peripheralDidUpdateName:(CBPeripheral *)peripheral
{
}

- (void)peripheral:(CBPeripheral *)peripheral didModifyServices:(NSArray *)invalidatedServices
{
}

@end
